<template>
  <a-drawer :visible="visible" title="声音克隆" @close="closeChange" :width="800">
    <template v-if="agreement || id">
      <div class="title_tips" v-if="false">
        <h2 class="title_tips_title">语音克隆训练</h2>
        <span>通过上传您录制的语音(时长<span class="dye">30s以上</span>,大小<span class="dye">10mM以内</span>)，轻松复刻您的专属音色</span>
      </div>
      <a-form layout="vertical">
        <a-form-item v-if="requiredInformationData.voice_name" v-bind="validateInfos.voice_name">
          <template #label>
            <span class="label">
              {{ requiredInformationData.voice_name.label }}
            </span>
            <a-tooltip>
              <template #title>
                {{ requiredInformationData.voice_name.tip.join("") }}
              </template>
              <question-circle-outlined v-if="requiredInformationData.voice_name.tip.length" />
            </a-tooltip>
          </template>
          <a-input v-model:value="modelRef.voice_name" :placeholder="'请输入' + requiredInformationData.voice_name.label"
            :maxlength="requiredInformationData.voice_name.max" :disabled="!modelRef?.isEdit" />
        </a-form-item>


        <!-- 上传个人音频 -->
        <a-form-item v-if="requiredInformationData.record_url" v-bind="validateInfos.record_url">
          <template #label>
            <span class="label">
              {{ requiredInformationData.record_url.label }}
            </span>
            <a-tooltip>
              <template #title>
                {{ requiredInformationData.record_url.tip.join("") }}
              </template>
              <question-circle-outlined />
            </a-tooltip>
          </template>
          <div class="tip_box">
            <div class="tips_title">音频要求</div>
            <div class="tips_content">
              <div class="tips_item">
                <div class="tips_item_title">音频格式支持：</div>
                <div class="tips_item_content">
                  <!-- wav、mp3、ogg、m4a、aac、pcm，其中pcm仅支持24k单通道 -->
                   <template v-if="requiredInformationData?.record_url?.tip">
                    <span>{{ requiredInformationData?.record_url?.tip.join('') }}</span>
                   </template>
                </div>
              </div>
              <div class="tips_item">
                <div class="tips_item_title">文件大小：</div>
                <div class="tips_item_content">目前限制单文件上传最大10MB
                </div>
              </div>

              <!-- <div class="tips_item">
                      <div class="tips_item_title">文件大小：</div>
                      <div class="tips_item_content">小于20MB</div>
                    </div>
                    <div class="tips_item">
                      <div class="tips_item_title">采样频率：</div>
                      <div class="tips_item_content">16.000kHz及以上</div>
                    </div> -->
            </div>
          </div>
          <div v-if="!modelRef.record_url" class="upload-dragger" @click="
            handleUploadChange(
              requiredInformationData.record_url.allow_extension,
              'record_url'
            )
            ">
            <div>
              <cu-icon class="icon-upload" type="icon-shangchuan"></cu-icon>
            </div>
            <div>请上传一段音频,用于声音克隆</div>
            <div style="color: #939393">点击此区域上传</div>
          </div>
          <div class="select_voice_style have_voice" v-if="modelRef.record_url">
            <DeleteOutlined class="del_icon" v-show="modelRef?.isEdit" @click="delRecordUrlVoice"></DeleteOutlined>
            <!-- 音频暂停状态 -->
            <PauseCircleOutlined class="voice_icon" v-if="playRecordUrlVoice" @click="playRecordUrlVoiceClick" />
            <!-- 音频播放状态 -->
            <PlayCircleOutlined v-else @click="playRecordUrlVoiceClick" class="voice_icon">
            </PlayCircleOutlined>
            <audio ref="voiceRecordUrl" @ended="endedRecordUrlChange" @play="onPlayRecordUrlChange"
              @pause="onPauseRecordUrlChange" :src="modelRef.record_url" controls></audio>
          </div>
        </a-form-item>
      </a-form>
    </template>
    <template v-else>
      <CloningProcess />
    </template>
    <template #footer>
      <a-row align="middle" :justify="!agreement && !id ? 'space-between' : 'end'">
        <a-col v-if="!agreement && !id">
          <a-checkbox v-model:checked="checked">
            我已阅读并同意 <a>《声音克隆协议》</a>
          </a-checkbox>
        </a-col>
        <a-col>
          <a-row align="middle" style="width: 100%">
            <a-button v-if="!agreement && !id" :disabled="!checked" type="primary" @click="nextStep">
              下一步
            </a-button>
            <a-button v-else type="primary" :loading="loading" :disabled="!modelRef?.isEdit" @click="debouncedstartCloning">
              开始克隆
            </a-button>
          </a-row>
        </a-col>
      </a-row>
    </template>
    <!-- 素材库 -->
    <ChooseMaterial useType="声音克隆" material_type="audio" :extension="extension" :isClip="false"
      :multiple="false" :visible="chooseMaterialVisible" @close="closeChooseMaterial"
      />


    <notVoiceNumDialog :currentNum="currentNum" :voiceNum="voiceNum" :name_unit="name_unit" :unit="unit"
      @handleOk="handleOk" @topUp="topUp" ref="notVoiceNumDialogRef">
    </notVoiceNumDialog>

  </a-drawer>
  <!-- 充值弹窗 -->
  <vipModal :visible="vipVisible" @close="vipVisible = false"></vipModal>
</template>

<script>
import { ref, watch, toRefs, defineComponent, reactive, computed } from "vue";
import request from "@/common/utils/request";
import { Form, message } from "ant-design-vue";
import store from "@/store/index.js";
import {
  DeleteOutlined,
  QuestionCircleOutlined,
  PlayCircleOutlined,
  PauseCircleOutlined,
} from "@ant-design/icons-vue";
// 克隆流程
import CloningProcess from "./CloningProcess.vue";
// 素材库
import ChooseMaterial from "@/views/shotstack/EditingCenter/modules/bottomSet/components/chooseMaterial.vue";
// 工具引入
import _ from "lodash";
import { debounce } from "lodash";

// 声音克隆消耗次数
import { VOICE_USE_NUM } from "@/common/utils/richTextProcessing.js"

// 充值弹窗
import vipModal from '@/socialMedia/Vip/vipModal.vue'

import notVoiceNumDialog from './notVoiceNumDialog.vue'

const useForm = Form.useForm;

export default defineComponent({
  name: "SoundCloningDrawer ",
  components: {
    ChooseMaterial,
    DeleteOutlined,
    QuestionCircleOutlined,
    CloningProcess,
    PlayCircleOutlined,
    PauseCircleOutlined,
    notVoiceNumDialog,
    vipModal,
  },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
    id: {
      type: [Number, String],
      default: '',
    },
  },
  setup(props, { emit }) {
    // 提示声音次数不足组件
    const notVoiceNumDialogRef = ref(null)
    const state = reactive({
      checked: false,
      agreement: false,
      extension: "",
      chooseMaterialVisible: false,
      uploadType: "",
      requiredInformationData: {},
      recordUrlList: [],
      authenticationList: [],
      loading: false,
      status: null,
      voiceState: false,
      playRecordUrlVoice: false,
      // 剩余人声克隆次数
      voiceNum: 0,
      currentNum: 0,
      unit: '',
      name_unit: "",

      vipVisible: false,
      uniqueId: ""
    });

    const modelRef = reactive({
      // 声音名字
      voice_name: "",
      // 选择的声音素材
      record_url: "",
      // 素材的id
      record_multimedia_id: '',
      // 允许编辑提交
      isEdit: true,
      uniqueId: ""
    });
    const rulesRef = reactive({
      voice_name: [
        {
          required: true,
          message: "请输入声音名称",
        },
      ],

      record_url: [
        {
          required: true,
          message: "请上传录音文件",
        },
      ],

    });
    const nextStep = () => {
      if (state.checked) {
        state.agreement = true;
      } else {
        state.agreement = false;
      }
    };

    // upload上传
    const handleUploadChange = (extension, type) => {
      if (state.status == 6) {
        message.warn("训练失败,不支持修改");
        return;
      }
      if (extension) {
        state.extension = extension
          .map((extension) => "." + extension)
          .join(",");
      }
      state.uploadType = type;
      state.chooseMaterialVisible = true;
    };

    const voiceRecordUrl = ref(null);
    const playRecordUrlVoiceClick = () => {
      console.log("录音文件");
      if (voiceRecordUrl.value) {
        if (voiceRecordUrl.value.paused) {
          voiceRecordUrl.value.play(); // 如果音频是暂停的，则播放
          state.playRecordUrlVoice = true;
        } else {
          voiceRecordUrl.value.pause(); // 如果音频正在播放，则暂停
          state.playRecordUrlVoice = false;
        }
      }
    };

    const onPlayRecordUrlChange = () => {
      state.playRecordUrlVoice = true;
    };
    // 音频暂停回调
    const onPauseRecordUrlChange = () => {
      console.log("暂停");
      state.playRecordUrlVoice = false;
    };

    // 音频结束回调
    const endedRecordUrlChange = () => {
      console.log("结束");
      state.playRecordUrlVoice = false;
    };

    //删除所选音频
    const delRecordUrlVoice = () => {
      modelRef.record_url = "";
    };

    const getVoiceTime = async () => {
      if (props.id) {
        handleOk()
        return
      }
      const res = await request.get("/work_ai", "/voice/customized/config/get", { number: 1 })

      console.log(res.pointInfo,   'res121313122312312');

      state.voiceNum = res.pointInfo.consumes
      state.name_unit = res.pointInfo.name
      state.unit = res.pointInfo.unit
      state.currentNum = res.pointInfo.current
      notVoiceNumDialogRef.value.showModal()
    }

    const getuniqueId = async () => {
      const res = await request.get("/work_ai", "/user/platform/uniqueId")
      modelRef.uniqueId = res.uniqueId
    }

    // 确认消耗, 进行合成
    const handleOk = () => {
      state.loading = true;
      console.log(modelRef, "modelRef");
      if (props.id) {
        modelRef.id = props.id;
        request
          .put("/work_ai", "/voice/customizedJob/update", modelRef)
          .then((res) => {
            if (res?.code && res.code != 1000) {
             emit("closeFn");
              throw new Error(res.msg);
            }
           
            state.loading = false;
            message.success("修改成功");
            emit("submitChange");
            console.log(res);
            
          })
          .catch((err) => {
            message.error(err.message || '合成失败');
            state.loading = false;
          });
        return;
      }
      // 新建 确保没有id 属性
      delete modelRef.id
      request
        .post("/work_ai", "/voice/customized/create", modelRef)
        .then((res) => {
          if (res?.code && res.code != 1000) {
             emit("closeFn");
            throw new Error(res.msg);
          }
          console.log(res, '声音创建');
          state.loading = false;
          message.success("提交成功");
          emit("submitChange");

         
        })
        .catch((err) => {
          message.error(err.message || '合成失败');
          state.loading = false;
        });
    }


    // 开始克隆
    const startCloning = () => {
      // 开始合成 表单校验之后 开始次数消耗校验
      validate().then(async () => {
        await getuniqueId ()
        getVoiceTime()

      });
    };

  const debouncedstartCloning = debounce(startCloning, 1000, {
 leading: true,
 trailing: false,
 });

    const { resetFields, validate, validateInfos } = useForm(
      modelRef,
      rulesRef
    );

    // 选择素材回调
    const closeChooseMaterial = (data) => {
      if (data) {
        console.log(data,'选择的声音');
        
        if (state.uploadType == "authentication_audio") {
          state.authenticationList = [data];
          modelRef.authentication_audio = data.material_url;
        }
        if (state.uploadType == "record_url") {
          state.recordUrlList = [data];
          modelRef.record_url = data.material_url;
          modelRef.record_multimedia_id = data.id;
        }
      }
      state.chooseMaterialVisible = false;
    };

    const getRequiredInformation = () => {
      request
        .get("/work_ai", "/voice/customized/required/information")
        .then((res) => {
          state.requiredInformationData = res.result;
          console.log(state.requiredInformationData, 'requiredInformationData');

          modelRef.scenario =
            state.requiredInformationData?.scenario?.select[0].value;
        });
    };

    const setModelRef = (state) => {
      for (let key in state) {
        if (Object.hasOwn(modelRef, key)) {
          modelRef[key] = state[key];
        }
      }
    };

    const getCustomizedInfoDetail = () => {
      request
        .get("/work_ai", "/voice/customizedInfo/detail", { id: props.id })
        .then((res) => {
          state.status = res.result.status;
          setModelRef(res.result);
          modelRef.text = res.result.demo_text || undefined;

          if (res.result.authentication_audio) {
            state.authenticationList = [res.result.authentication_audio];
            modelRef.authentication_audio = res.result.authentication_audio;
          } else {
            state.authenticationList = [];
            modelRef.authentication_audio = "";
          }

          if (res.result.record_url) {
            state.recordUrlList = [res.result.record_url];
            modelRef.record_url = res.result.record_url;
          } else {
            state.recordUrlList = [];
            modelRef.record_url = "";
          }
        });
    };

    // 未初始化+初始化失败 （status = 0 || status = 7） 支持 所有信息变更
    const informationChanges = computed(() => {
      if (!props.id) {
        return true;
      }
      return state.status == 0 || state.status == 7;
    });

    // 音频检测失败（status = 8） 支持修改 部分信息 认证音频[authentication_audio]、RecordUrl 对应的音频序号[audio_id]、录音URL[record_url]、示例URL[demo_audio]、示例文本[text]
    const modifySomeInformation = computed(() => {
      if (!props.id) {
        return false;
      }
      return state.status == 8;
    });

    // 重新提交 但不支持信息修改
    const notSupported = computed(() => {
      if (!props.id) {
        return false;
      }
      return state.status == 6 || (state.status == 2 && modelRef.audio_pass_status == 2);
    });

    const closeChange = () => {
      resetFields();
      emit("closeChange");
    };

    watch(
      () => props.visible,
      (val) => {
        if (val) {
          // 重置数据
          for (let key in modelRef) {
            modelRef[key] = ''
          }
          modelRef.isEdit = true
          getRequiredInformation();
          if (props.id) {
            getCustomizedInfoDetail();
          }
        } else {
          state.checked = false;
          state.agreement = false;
          state.authenticationList = [];
          modelRef.authentication_audio = "";
          state.recordUrlList = [];
          modelRef.record_url = "";
          store.dispatch("setApplicationMaterialData", {});
        }
      }
    );

    const topUp = () => {
      state.vipVisible = true
    }
    watch(()=>store.getters.applicationMaterialData,(data)=>{
      console.log(data,'xxxxxxxxxxxxxxxxxxxx');
      
      if(Object.keys(data).length){
        state.checked = true;
      setTimeout(() => {
        modelRef.record_url = data.material_url; 
      },200)
      } 
    },{deep:true,immediate:true})
    return {
      ...toRefs(state),
      closeChange,
      topUp,
      handleOk,
      notVoiceNumDialogRef,
      validateInfos,
      VOICE_USE_NUM,
      resetFields,
      modelRef,
      nextStep,
      startCloning,
      handleUploadChange,
      closeChooseMaterial,
      informationChanges,
      modifySomeInformation,
      notSupported,
      delRecordUrlVoice,
      endedRecordUrlChange,
      onPauseRecordUrlChange,
      onPlayRecordUrlChange,
      playRecordUrlVoiceClick,
      voiceRecordUrl,
      debouncedstartCloning
    };
  },
});
</script>

<style lang="less" scoped>
// 声音克隆页面, 顶部小标题
.title_tips {
  display: flex;
  flex-direction: column;
  margin-bottom: 20px;

  span {
    color: #333;
  }

  .dye {
    color: #fc7e42;
  }

  h2 {
    margin: 0;
    margin-bottom: 5px;
    padding: 0;
    font-size: 14px;
    font-weight: 900;
  }
}

// 收集音频表单下方的提示
.tip_box {
  background-color: #f6f7f9;
  display: flex;
  flex-direction: column;
  padding: 5px 12px;
  margin-bottom: 15px;

  .tips_title {
    font-weight: 700;
  }

  .tips_content {
    display: flex;
    flex-wrap: wrap;
    // justify-content: space-between;
    gap: 5px 20px;

    .tips_item {
      display: flex;

      .tips_item_title {
        color: #333333;
      }

      .tips_item_content {
        color: #888888;
      }
    }
  }
}
.label {
  font-weight: 600;
  margin-right: 5px;
}

.audio-requirements {
  background: #f7f8fa;
  padding: 10px;
  margin-bottom: 15px;
}

.icon-upload {
  font-size: 55px;
}

.upload-dragger {
  width: 100%;
  height: 130px;
  border: 1px dashed rgba(222, 222, 222, 1);
  background: #fafafa;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  transition: all ease-out 0.3s;

  &.upload-dragger:hover {
    border: 1px dashed rgba(82, 151, 255, 1);
  }
}

.file-list {
  padding-left: 5px;
  margin: 5px 0;

  &.file-list:hover {
    background: #f5f5f5;
  }

  .delete-outlined {
    color: red;
  }
}

.select_voice_style {
  height: 200px;
  width: 100%;
  border-radius: 8px;
  border: 1px solid #c0c0c0;
  display: flex;

  &:hover {
    border-color: var(--ss-primary-color-hover);
    color: var(--ss-primary-color-hover);
  }
}

// 选择了音频的样式
.have_voice {
  // flex-direction: column;
  // align-items: center;
  // justify-content: space-between;
  padding: 15px;
  position: relative;
  transition: all 0.3s;

  .voice_icon {
    color: #666666;
    cursor: pointer;
    font-size: 50px;
    position: absolute;
    top: 35%;
    left: 50%;
    transform: translate(-50%, -50%);

    &:hover {
      color: var(--ss-primary-color-hover);
    }
  }

  .del_icon {
    color: #666666;
    cursor: pointer;
    position: absolute;
    right: 10px;
    top: 10px;
    font-size: 23px;

    &:hover {
      color: var(--ss-error-color);
    }
  }

  audio {
    width: calc(100% - 30px);
    position: absolute;
    bottom: 15px;
    left: 15px;
  }
}
</style>
